package model;

import ilog.concert.*;
import ilog.concert.IloCopyManager.Check;
import ilog.cplex.*;
import ilog.opl.*;

public class model
{
    static final String DATADIR = ".";
    static final String MODEL_FILE = "knapsack";
    //static final String MODEL_FILE = "mulprod";
    static final String MPS_FILE = "example";
    static public void main(String[] args) throws Exception
    {
      int status = 127;    
      try {
        IloOplFactory.setDebugMode(false);
        IloOplFactory oplF = new IloOplFactory();
        IloOplErrorHandler errHandler = oplF.createOplErrorHandler();
        IloOplModelSource modelSource = oplF.createOplModelSource(DATADIR
                + "/" + MODEL_FILE + ".mod");
        IloOplSettings settings = oplF.createOplSettings(errHandler);
        IloOplModelDefinition def = oplF.createOplModelDefinition(modelSource,settings);
        IloCplex cplex = oplF.createCplex();
        cplex.setOut(null);
        IloOplModel opl = oplF.createOplModel(def, cplex);
        IloOplDataSource dataSource = oplF.createOplDataSource(DATADIR
                + "/" + MODEL_FILE + ".dat");
        opl.addDataSource(dataSource);
        opl.generate();
        //opl.printInternalData(System.out);
        //IloNumVar[] vars = new IloNumVar[3];
        //vars[0] = cplex.numVar(0, Double.MAX_VALUE, "x");
        //vars[1] = cplex.numVar(0, Double.MAX_VALUE, "y");
        //vars[2] = cplex.numVar(0, Double.MAX_VALUE, "z");
       
        
        System.out.println("The model is MIP: " + (cplex.isMIP() ? "Yes" : "No"));
        //System.out.println(cplex.toString());
        //cplex.add(vars);
        if (cplex.solve())
        {
            System.out.println("OBJECTIVE: " + opl.getCplex().getObjValue());
            opl.postProcess();
            cplex.exportModel(DATADIR + "/" + MPS_FILE + ".mps");
            //naive cruncher 
            printVars(new IloCplex(),DATADIR + "/" + MPS_FILE + ".mps");
            //opl.printSolution(System.out);
        }
        else
        {
            System.out.println("No solution!");
        }
        
        
        //System.out.println("cplex.toString() " + cplex.toString());
        //query the solution
        IloNumVar[] vars1 =  parse(cplex.getModel());
        //System.out.println(vars1.length);
        //for (int i = 0 ; i < vars.length; i++ )
        //{
        //	System.out.println(vars[i].getName());
        //}
        //query the model data elements
        IloOplDataElements dataElements = opl.makeDataElements();

        for (java.util.Iterator it = dataElements.getElementIterator(); it.hasNext(); )
        {
            IloOplElement p = (IloOplElement)it.next();
            System.out.println("Data element [" + p + "] type is " + p.getElementType());
        }
        System.out.println("---------------------");

        oplF.end();
		status = 0;
      } catch (IloOplException ex) {
        System.err.println("### OPL exception: " + ex.getMessage());
        ex.printStackTrace();
        status = 2;
      } catch (IloException ex) {
        System.err.println("### CONCERT exception: " + ex.getMessage());
        ex.printStackTrace();
        status = 3;
      } catch (Exception ex) {
        System.err.println("### UNEXPECTED UNKNOWN ERROR ...");
        ex.printStackTrace();
        status = 4;
      }
      System.exit(status);
    }
 
    static private void printVars(IloCplex cplex, String filename)
    {
    try{
    cplex.importModel(filename);

    // Solve the model and display the solution if one was found
    if ( cplex.solve() ) {
       System.out.println("Solution status = " + cplex.getStatus());
       System.out.println("Solution value  = " + cplex.getObjValue());

       // Access the IloLPMatrix object that has been read from a file in
       // order to access variables which are the columns of the LP.  The
       // method importModel() guarantees that exactly one IloLPMatrix
       // object will exist, which is why no tests or iterators are
       // needed in the following line of code.
       IloLPMatrix lp = (IloLPMatrix)cplex.LPMatrixIterator().next();
       IloNumVar[] vars = lp.getNumVars();
       
       double[] vals = cplex.getValues(lp);
       for (int j = 0; j < vals.length; ++j)
          System.out.println("Variable " + vars[j] + ": Value = " + vals[j]);

       try {     // basis may not exist
          IloCplex.BasisStatus[] cstat =
                cplex.getBasisStatuses(lp.getNumVars());
          for (int j = 0; j < vals.length; ++j)
             System.out.println("Variable " + j +
                                ": Basis Status = " + cstat[j]);
       }
       catch (Exception e) {
       }

       System.out.println("Maximum bound violation = " +
              cplex.getQuality(IloCplex.QualityType.MaxPrimalInfeas));
    }
    cplex.end();
 }
 catch (IloException e) {
    System.err.println("Concert exception caught: " + e);
    e.printStackTrace();
 }
}
    
    
    
    private static IloNumVar[] parse(ilog.concert.IloModel model) throws IloException {
        java.util.HashSet<IloNumVar> vars = new java.util.HashSet<IloNumVar>();
        java.util.Iterator it = model.iterator();
        IloLinearNumExpr expr;
        IloLinearNumExprIterator it2;
        while (it.hasNext()) {
          IloAddable thing = (IloAddable) it.next();
          System.out.println(thing.toString());
          if (thing instanceof IloRange) {
            expr = (IloLinearNumExpr) ((IloRange) thing).getExpr();
            it2 = expr.linearIterator();
            while (it2.hasNext()) {
              vars.add(it2.nextNumVar());
            }
          } else if (thing instanceof IloObjective) {
            expr = (IloLinearNumExpr) ((IloObjective) thing).getExpr();
            it2 = expr.linearIterator();
            while (it2.hasNext()) {
              vars.add(it2.nextNumVar());
            }
          } else if (thing instanceof IloSOS1) {
            vars.addAll(java.util.Arrays.asList(((IloSOS1) thing).getNumVars()));
          } else if (thing instanceof IloSOS2) {
            vars.addAll(java.util.Arrays.asList(((IloSOS2) thing).getNumVars()));
          } else if (thing instanceof IloLPMatrix) {
            vars.addAll(java.util.Arrays.asList(((IloLPMatrix) thing).getNumVars()));
          }
        }
        IloNumVar[] varray = vars.toArray(new IloNumVar[1]);
        return varray;
      }
}
